package org.dromara.web.plugins.provider;


import cn.hutool.crypto.Mode;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.dromara.common.core.exception.user.UserException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.dao.business.domain.Model;
import org.dromara.web.controller.app.req.ChatBody;
import org.dromara.web.plugins.file.LocalFileResolver;
import org.dromara.web.plugins.provider.impl.*;
import org.dromara.web.plugins.search.SearchComponent;
import org.dromara.web.plugins.search.SearchUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class ModelProviderFactory implements InitializingBean {
    @Autowired
    ChatProviderOpenAI chatProviderOpenAI;
    @Autowired
    ChatProviderClaude chatProviderClaude;
    @Autowired
    ChatProviderOpenRouter chatProviderOpenRouter;
    @Autowired
    ChatProviderMai chatProviderMai;
    @Autowired
    ChatProviderLlama chatProviderLlama;
    @Autowired
    ChatProviderGemini chatProviderGemini;
    @Autowired
    ChatProviderTongYiQianWen chatProviderTongYiQianWen;
    @Autowired
    ChatProviderDeepSeek chatProviderDeepSeek;
    @Autowired
    ChatProviderDoubao chatProviderDoubao;
    @Autowired
    ChatProviderMoonshot chatProviderMoonshot;
    @Autowired
    ChatProviderXunfei chatProviderXunfei;
    @Autowired
    ChatProviderBaiduqianfan chatProviderBaiduqianfan;
    @Autowired
    ChatProviderAliyun chatProviderAliyun;
    @Autowired
    ChatProviderTencent chatProviderTencent;

    @Autowired
    ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Autowired
    LocalFileResolver localFileResolver;
    @Autowired
    SearchComponent searchComponent;
    @Autowired
    SearchUtils searchUtils;


    private Map<String, ChatProvider> providers = new HashMap<>();

    @Override
    public void afterPropertiesSet() throws Exception {
        providers.put(ChatProviderOpenAI.MODEL_TYPE, chatProviderOpenAI);
        providers.put(ChatProviderClaude.MODEL_TYPE, chatProviderClaude);
        providers.put(ChatProviderOpenRouter.MODEL_TYPE, chatProviderOpenRouter);
        providers.put(ChatProviderMai.MODEL_TYPE, chatProviderMai);
        providers.put(ChatProviderLlama.MODEL_TYPE, chatProviderLlama);
        providers.put(ChatProviderGemini.MODEL_TYPE, chatProviderGemini);
        providers.put(ChatProviderTongYiQianWen.MODEL_TYPE, chatProviderTongYiQianWen);
        providers.put(ChatProviderDeepSeek.MODEL_TYPE, chatProviderDeepSeek);
        providers.put(ChatProviderDoubao.MODEL_TYPE, chatProviderDoubao);
        providers.put(ChatProviderMoonshot.MODEL_TYPE, chatProviderMoonshot);
        providers.put(ChatProviderXunfei.MODEL_TYPE, chatProviderXunfei);
        providers.put(ChatProviderBaiduqianfan.MODEL_TYPE, chatProviderBaiduqianfan);
        providers.put(ChatProviderAliyun.MODEL_TYPE, chatProviderAliyun);
        providers.put(ChatProviderTencent.MODEL_TYPE, chatProviderTencent);
    }

    /**
     * @param body
     */
    public void chat(ChatBody body, Model model, SseEmitter sseEmitter, ChatCompletionListener completionListener, boolean mute) {

        ChatProvider chatProvider = providers.get(model.getManu());
        if (chatProvider == null) {
            throw new UserException("model.notmatch");
        }

        if (StringUtils.isNotEmpty(body.getFileId())) {
            String text = localFileResolver.resolveFileToText(body.getFileId());
            String content = String.format("文件的内容是: %s  请基于文件内容回答用户问题", text);
            body.setPrompt(content);
        } else if (body.getNetwork() != null && body.getNetwork()) {
            // 获取搜索结果
            StringBuilder context = new StringBuilder();
            List<Map<String, String>> searchResults = searchUtils.tavilySearch(body.getMessage());
            if (!searchResults.isEmpty()) {
                System.out.println("search results size（联网搜索个数）: " + searchResults.size());
                context.append("\n\n联网搜索结果：\n");
                JSONArray jsonArray = new JSONArray();
                for (int i = 0; i < searchResults.size(); i++) {
                    Map<String, String> result = searchResults.get(i);
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("title", String.format("%d. %s", i + 1, result.get("title").replace("\"", "").replace("\n", "")));
                    jsonObject.put("url", result.get("url").replace("\"", ""));
                    jsonArray.add(jsonObject);
                    context.append(String.format("\n%d. %s\n", i + 1, result.get("title")));
                    context.append(String.format("   %s\n", result.get("content")));
                    context.append(String.format("   来源: %s\n", result.get("url")));
                }
                body.setReferencesJson(jsonArray.toJSONString());
            }
            // 如果有上下文，添加系统消息
            if (!context.isEmpty()) {
                body.setPrompt("请基于以下参考信息回答用户问题：\n" + context);
            }

//            String searchResult = searchComponent.networkSearch(body.getMessage());
////            body.setPrompt(String.format("请基于以下内容: %s 回答用户问题", searchResult));
//            // https://blog.csdn.net/qq_35650513/article/details/144572824
//            String message = "我将提供一段来自互联网的资料信息, 请根据这段资料以及用户提出的问题来给出回答。请确保在回答中使用Markdown格式，并在回答末尾列出参考资料。如果资料中的信息不足以回答用户的问题，可以根据自身知识库进行补充，或者说明无法提供确切的答案。\n" +
//                "网络资料:\n"
//                + "============\n"
//                + searchResult
//                + "============\n"
//                + "用户问题:\n"
//                + "============\n"
//                + body.getMessage()
//                + "============\n";
//            body.setPrompt(message);
        }
        // 调用相应的api来发送请求
        chatProvider.chat(body, model.getValue(), sseEmitter, completionListener, mute);
    }


    public String chatResponse(Model model, String question) {
        ChatProvider chatProvider = providers.get(model.getManu());
        if (chatProvider == null) {
            throw new UserException("model.notmatch");
        }

        return chatProvider.chatResponse(model, question);
    }
}
